import requests
import json
from pathlib import Path
import sys
import os
from PyQt6.QtWidgets import QMessageBox
from PyQt6.QtCore import QThread, pyqtSignal
from .logger import Logger
from .update_config import UPDATE_CONFIG

# 获取日志实例
logger = Logger.get_logger()

# 尝试导入 oss2，如果失败则使用备用方案
try:
    import oss2
    HAS_OSS = True
except ImportError:
    HAS_OSS = False
    logger.warning("oss2 模块未安装，将仅使用 GitHub 更新源")

class UpdateChecker(QThread):
    """更新检查器"""
    check_finished = pyqtSignal(bool)  # 发送是否有更新的信号
    update_progress = pyqtSignal(str)  # 发送更新进度的信号
    
    def __init__(self, current_version, update_url):
        super().__init__()
        self.current_version = current_version
        self.update_url = update_url
        self.gitee_config = UPDATE_CONFIG['GITEE_RELEASE']
        
    def run(self):
        try:
            # 检查Gitee Release
            latest_release = self.check_gitee_release()
            if latest_release:
                if self.compare_versions(latest_release['version'], self.current_version):
                    # 有新版本
                    self.prepare_update(latest_release)
                    self.check_finished.emit(True)
                    return
            
            # 没有更新
            self.check_finished.emit(False)
            
        except Exception as e:
            logger.error(f"检查更新失败: {str(e)}")
            self.check_finished.emit(False)
    
    def check_gitee_release(self):
        """检查Gitee Release"""
        try:
            # 构建API URL
            api_url = f"https://gitee.com/api/v5/repos/{self.gitee_config['owner']}/{self.gitee_config['repo']}/releases/latest"
            
            # 添加访问令牌
            params = {}
            if self.gitee_config.get('access_token'):
                params['access_token'] = self.gitee_config['access_token']
            
            # 发送请求
            response = requests.get(api_url, params=params)
            
            if response.status_code == 200:
                release_info = response.json()
                
                # 解析版本信息
                version_info = {
                    'version': release_info['tag_name'].lstrip('v'),
                    'description': release_info['body'],
                    'download_url': None,
                    'assets': []
                }
                
                # 获取资源文件
                for asset in release_info.get('assets', []):
                    if asset['name'].endswith('.zip'):
                        version_info['download_url'] = asset['browser_download_url']
                        version_info['assets'].append({
                            'name': asset['name'],
                            'url': asset['browser_download_url']
                        })
                
                if version_info['download_url']:
                    return version_info
                
            return None
            
        except Exception as e:
            logger.error(f"检查Gitee更新失败: {str(e)}")
            return None
    
    def compare_versions(self, new_version, current_version):
        """比较版本号"""
        try:
            new_parts = [int(x) for x in new_version.split('.')]
            current_parts = [int(x) for x in current_version.split('.')]
            
            for new, current in zip(new_parts, current_parts):
                if new > current:
                    return True
                elif new < current:
                    return False
            
            return len(new_parts) > len(current_parts)
            
        except Exception as e:
            logger.error(f"版本比较失败: {str(e)}")
            return False
    
    def prepare_update(self, release_info):
        """准备更新文件"""
        try:
            # 创建更新脚本
            script_path = self.create_update_script(release_info)
            
            # 保存更新信息
            update_info = {
                'version': release_info['version'],
                'description': release_info['description'],
                'script_path': str(script_path)
            }
            
            with open('update_info.json', 'w', encoding='utf-8') as f:
                json.dump(update_info, f, ensure_ascii=False, indent=2)
                
        except Exception as e:
            logger.error(f"准备更新失败: {str(e)}")
            raise
    
    def create_update_script(self, release_info):
        """创建更新脚本"""
        script_content = f'''
import os
import sys
import shutil
import requests
import zipfile
from pathlib import Path

def update_app():
    try:
        print("开始下载更新...")
        
        # 下载更新包
        url = "{release_info['download_url']}"
        response = requests.get(url, stream=True)
        
        with open("updates/update.zip", "wb") as f:
            for chunk in response.iter_content(chunk_size=8192):
                if chunk:
                    f.write(chunk)
        
        print("下载完成，开始解压...")
        
        # 解压更新包
        with zipfile.ZipFile("updates/update.zip", 'r') as zip_ref:
            zip_ref.extractall("updates/temp")
        
        print("解压完成，开始更新文件...")
        
        # 复制新文件
        src_dir = Path("updates/temp/MiaoShenAI")
        dst_dir = Path(".")
        
        for src_path in src_dir.rglob("*"):
            if src_path.is_file():
                rel_path = src_path.relative_to(src_dir)
                dst_path = dst_dir / rel_path
                dst_path.parent.mkdir(parents=True, exist_ok=True)
                shutil.copy2(src_path, dst_path)
        
        print("更新完成，清理临时文件...")
        
        # 清理临时文件
        shutil.rmtree("updates/temp")
        os.remove("updates/update.zip")
        
        # 重启应用
        os.startfile("MiaoShenAI.exe")
        
    except Exception as e:
        with open("update_error.log", "w") as f:
            f.write(f"更新失败: {str(e)}")

if __name__ == '__main__':
    update_app()
'''
        
        script_path = Path("updates/update.py")
        script_path.parent.mkdir(exist_ok=True)
        
        with open(script_path, 'w', encoding='utf-8') as f:
            f.write(script_content)
        
        return script_path

class Updater:
    def __init__(self):
        self.settings_file = 'settings.json'
        self.load_settings()
        
    def load_settings(self):
        """加载设置"""
        try:
            with open(self.settings_file, 'r', encoding='utf-8') as f:
                self.settings = json.load(f)
        except Exception as e:
            logger.error(f"加载设置失败: {str(e)}")
            self.settings = {}
    
    def get_current_version(self):
        """获取当前版本"""
        return self.settings.get('version', {}).get('current', '1.0.0')
    
    def get_update_url(self):
        """获取更新服务器地址"""
        return self.settings.get('version', {}).get('update_url', '')
    
    def download_update(self, update_info):
        """下载更新"""
        try:
            download_path = Path("updates")
            download_path.mkdir(exist_ok=True)
            
            file_path = download_path / "update.zip"
            
            # 下载更新包
            response = requests.get(update_info['download_url'], stream=True)
            total_size = int(response.headers.get('content-length', 0))
            
            with open(file_path, 'wb') as f:
                for chunk in response.iter_content(chunk_size=8192):
                    f.write(chunk)
            
            return self.install_update(file_path)
            
        except Exception as e:
            logger.error(f"下载更新失败: {str(e)}")
            return False
    
    def download_from_github(self, url, file_path):
        """从GitHub下载更新"""
        response = requests.get(url, stream=True)
        total_size = int(response.headers.get('content-length', 0))
        
        with open(file_path, 'wb') as f:
            for chunk in response.iter_content(chunk_size=8192):
                f.write(chunk)
    
    def download_from_oss(self, object_name, file_path):
        """从OSS下载更新"""
        auth = oss2.Auth(
            UPDATE_CONFIG['OSS_CONFIG']['access_key'],
            UPDATE_CONFIG['OSS_CONFIG']['access_secret']
        )
        bucket = oss2.Bucket(
            auth,
            UPDATE_CONFIG['OSS_CONFIG']['endpoint'],
            UPDATE_CONFIG['OSS_CONFIG']['bucket']
        )
        
        bucket.get_object_to_file(object_name, file_path)
    
    def install_update(self, update_file):
        """安装更新"""
        try:
            # 创建更新脚本
            update_script = self.create_update_script()
            
            # 启动更新脚本
            if sys.platform == 'win32':
                os.startfile(update_script)
            else:
                os.system(f'python "{update_script}"')
            
            return True
            
        except Exception as e:
            logger.error(f"安装更新失败: {str(e)}")
            return False
    
    def create_update_script(self):
        """创建更新脚本"""
        script_content = '''
import os
import sys
import time
import shutil
import zipfile
from pathlib import Path

def update_app():
    try:
        # 等待主程序退出
        time.sleep(2)
        
        # 解压更新文件
        with zipfile.ZipFile("updates/update.zip", 'r') as zip_ref:
            zip_ref.extractall("updates/temp")
        
        # 复制新文件
        src_dir = Path("updates/temp")
        dst_dir = Path(".")
        
        for src_file in src_dir.rglob("*"):
            if src_file.is_file():
                dst_file = dst_dir / src_file.relative_to(src_dir)
                dst_file.parent.mkdir(parents=True, exist_ok=True)
                shutil.copy2(src_file, dst_file)
        
        # 清理临时文件
        shutil.rmtree("updates/temp")
        os.remove("updates/update.zip")
        
        # 重启应用
        os.startfile("MiaoShenAI.exe")
        
    except Exception as e:
        with open("update_error.log", "w") as f:
            f.write(f"更新失败: {str(e)}")

if __name__ == '__main__':
    update_app()
'''
        
        script_path = Path("updates/update.py")
        script_path.parent.mkdir(exist_ok=True)
        
        with open(script_path, 'w', encoding='utf-8') as f:
            f.write(script_content)
        
        return script_path 